﻿//
// © Algobox Ltd - Benn Eichhorn
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Algobox.Objects.Finance.Assets.Stock;

namespace Algobox.Objects.Finance.Orders
{
    public class Order
    {
        #region Constructors

        public Order(string account, StockListing stock, bool isBuy, decimal price, uint quantity, OrderType type, TimeInForce tif)
        {
            Stock = stock;
            IsBuy = isBuy;
            Price = price;
            Quantity = quantity;
            Account = account;
            Type = type;
            TIF = tif;
            State = Order.Status.Initialised;
            TimeCreated = DateTime.Now;
            _clOrdId = GenerateClientOrderId();
        }

        static Order()
        {
            _processId = System.Diagnostics.Process.GetCurrentProcess().Id;
        }

        #endregion

        //////////

        #region Member Variables

        private static long _orderIdCounter = 0;
        private static int _processId = 0;

        private string _clOrdId;
        private string _clOrdIdPrevious;

        #endregion

        //////////

        #region Properties

        public string OrderIdClient { get { return _clOrdId; } set { _clOrdIdPrevious = _clOrdId; _clOrdId = value; } }
        public string OrderIdClientPrevious { get { return _clOrdIdPrevious; } }
        public StockListing Stock { get; private set; }
        public bool IsBuy { get; private set; }
        public string Account { get; private set; }
        public OrderType Type { get; private set; }
        public TimeInForce TIF { get; private set; }
        public DateTime TimeCreated { get; private set; }

        public decimal Price { get; set; }
        public decimal PriceAverage { get; set; }
        public uint Quantity { get; set; }
        public DateTime TimeUpdated { get; set; }
        public string OrderIdExchange { get; set; }
        public string OrderIdHost { get; set; }
        public uint QuantityFilled { get; set; }
        public uint QuantityRemaining { get; set; }
        public Status State { get; set; }
        public string Text { get; set; }
       
        public bool IsComplete { get { return State == Order.Status.Filled || State == Order.Status.Canceled || State == Order.Status.Stopped; } }

        #endregion

        //////////

        #region Functions

        public string GenerateClientOrderId()
        {
            return Account + DateTime.Now.ToString("-yyMMddHHmmss-") + _processId + "-" + System.Threading.Interlocked.Increment(ref _orderIdCounter);
        }

        public override string ToString()
        {
            return String.Format("{0} {1} {2} {3} {4} {5} {6}",
                Stock.ToString(),
                (IsBuy ? "" : "-") + Quantity + "@" + Price,
                TIF,
                Type,
                OrderIdClient, 
                OrderIdHost,
                OrderIdExchange);
        }

        #endregion

        //////////

        #region Enums
        
        public enum OrderType
        {
            Limit,
            LimitOnClose,
            Market,
            MarketOnClose,
            Stop,
            StopLimit,
            Peg,
            ServerSideStop,
            ServerSideStopLimit,
            TrailingStop
        }

        public enum TimeInForce
        {
            DAY,
            GTC,
            GTX,
            FOK,
            IOC,
            OPG
        }

        public enum Status
        {
            Initialised,
            PendingNew,
            PendingCancel,
            PendingReplace,
            New,
            Canceled,
            Replaced,
            Filled,
            FilledPartial,
            Stopped,
            Updated,
            Rejected,
            Unknown
        }

        #endregion
    }
}
